# -*- coding: utf-8 -*-
"""产品预订"""
import json
import copy
import datetime
import uuid

from flask import Blueprint, jsonify, request, g, current_app, abort, \
    render_template
from flask.views import MethodView, View

from app.utils.html5 import Html5BaseMixin
from app.models import Product, Mtu, ProductSKU, UserPlan, Order
from app.constants import MTU_TYPE, form_field_dict
from app.utils import safe_int, smart_str, get_objectId
from app.controllers import get_order_edit_data, get_productsku_blackout_date
from app.forms import ProductOrderForm


# __all__ = ['booking']
# booking = Blueprint('booking', __name__)

class ProductTypesView(MethodView, Html5BaseMixin):
    TEMPLATE = 'mobile/tripproduct/vacation_type.html'

    def get(self, product_id):
        data = self._init_data(request)
        # ua = request.headers.get('USER_AGENT', '').lower()
        ua = request.breadtrip.user_agent
        value = request.args.get('value')
        category = safe_int(value.split('_')[-1]) if value else 0

        # get product and product types
        product = get_object_or_404(Product, is_active=True, published=True,
                                    pk=id_decrypt(safe_int(product_id)))
        ptypes = ProductType.objects.filter(product=product, is_active=True)

        adult_types = {
            'name': '成人',
            'selected': False if category == 2 else True,
            'types': [],
        }
        child_types = {
            'name': '儿童',
            'selected': True if category == 2 else False,
            'types': [],
        }
        type_dict = {
            'category': [],
        }

        # get type data
        for ptype in ptypes:
            pk = ptype.pk
            # if ptype.is_null:
            #     key = '%s_%s' % (pk, 0)
            #     adult_types['types'].append({
            #         'name': ptype.name,
            #         'price': safe_int(ptype.null_fee),
            #         'describe': ptype.description,
            #         'selected': True if key == value else False,
            #         'value': key,
            #     })
            #     continue
            if ptype.is_adult and ptype.adult_fee:
                key = '%s_%s' % (pk, 1)
                adult_types['types'].append({
                    'name': ptype.name,
                    'price': safe_int(ptype.adult_fee),
                    'describe': ptype.description,
                    'selected': True if key == value else False,
                    'value': key,
                })
            if ptype.is_child and ptype.child_fee:
                key = '%s_%s' % (pk, 2)
                child_types['types'].append({
                    'name': ptype.name,
                    'price': safe_int(ptype.child_fee),
                    'describe': ptype.child_description,
                    'selected': True if key == value else False,
                    'value': key,
                })

        type_dict['category'].append(adult_types)
        if child_types['types']:
            type_dict['category'].append(child_types)

        data.update(
            type_dict=json.dumps(type_dict),
            product_id=product.id,
            is_breadtrip=True if 'breadtrip' in ua and \
                                 'vacation' not in ua else False,
        )
        return render(request, self.TEMPLATE, data, use_jinja2=True)


class ProductOrderView(MethodView, Html5BaseMixin):
    """
    产品订单处理(用户填写订单页面)
    """
    template_name = 'mobile/tripproduct/vacation_order.html'

    def product_type_handle(self, request, product):
        """
            产品类型处理
            产品有type和types属性
                types:多种产品类型，与is_type_lists一起使用
                type:单一产品类型
                [{
                    'name':'购买类headers型',
                    'name_en':'obj_1',
                    'url':'',
                    'type':url,
                    'value':''
                }
                {
                    'name':'数量',
                    'name_en':'count',
                    'url':'',
                    'type':'number',
                    'value':''
                }
                {
                    'name':'天数',
                    'name_en':'day',
                    'type':'number',
                    'value':''
                }
                {
                    'name':'价格',
                    'name_en':'obj_1',
                    'type':string,
                    'value':2399
                }]
        """
        # ptypes = ProductType.objects.filter(product=product, is_active=True)
        product_skus = product.productskus
        is_add_product_type = False
        total_price = 0
        ptype_data = []
        # for sku in product_skus:
        #     print sku.id
        #     print sku.product

        if product_skus:
            if len(product_skus) == 1:
                is_add_product_type = False
            else:
                is_add_product_type = True

            # default_ptypes = product_skus.filter(is_default=True)
            default_ptypes = [sku for sku in product_skus if sku.is_default]
            if default_ptypes:
                ptype = default_ptypes[0]
            else:
                ptype = list(product_skus)[0]
            # print '*' * 99
            # print ptype.id
            # print ptype.product
            ptype.__dict__.update(ptype.get_info('adult'))
            total_price = ptype.fee
            types_url = 'http://' + request.headers[
                'HOST'] + '/product/%s/types/' % (product.id)
            # types_url = ''

            ptype_data = [
                {
                    "name": "购买类型",
                    "name_en": "ptype",
                    "type": "url",
                    "url": types_url,
                    "value": ptype.name,
                },
                {
                    "name": "数量",
                    "name_en": 'count',
                    "type": "number",
                    "url": '',
                    "value": 1,
                },
                {
                    "name": "价格",
                    "name_en": 'price',
                    "type": "string",
                    "value": ptype.fee,
                },
                {
                    "name": "类型值",
                    # "name_en":ptype.name_en,
                    "name_en": "pcategory",
                    "type": "hidden",
                    "value": str(ptype.id) + '_' + str(ptype.category),
                }
            ]

        return is_add_product_type, total_price, ptype_data

    # def get_user_agent_info(self):
    #     """
    #     获取user agent 信息
    #     ~~~~~~~~~~~~~~~~~~~
    #     Returns:
    #     {
    #         'is_breadtrip': True or False,
    #         'is_vacation': True or False
    #     }
    #     """
    #     # print '*' * 99
    #     # print type(request)
    #     # print request.headers
    #     # print '*' * 99
    #     # ua = request.META['HTTP_USER_AGENT'].lower()
    #     ua = request.headers.get('USER_AGENT', 'TEST_CLIENT').lower()
    #     ret = {}
    #     if 'breadtrip' in ua and 'vacation' not in ua:
    #         ret['is_breadtrip'] = True
    #     else:
    #         ret['is_breadtrip'] = False
    #     ret['is_vacation'] = True if 'vacation' in ua else False
    #     return ret

    # def get_custom_option_data(self, request, ptype_data, product_id):
    #     """
    #     获取用户从后台填写的勾选项与自定义项数据
    #     """
    #     # customcategory = ProductCustomCategory.objects.filter(
    #     #     product__id=int(product_id), is_active=True)
    #     product = Product.objects.get(pk=product_id)
    #     customcategory = product.product_custom_category
    #     field_list = []  # 复选框项数据
    #     custom_option = []  # 自定义项数据
    #     tpl_json = {'contact': [], 'extended': [], 'basic': []}
    #
    #     last_order_info = self.get_last_order_contact_info(request)
    #
    #     is_baby = False  # 用于是否携带婴儿复选框判断
    #     for option in customcategory:
    #         if str(option.attribute_name) == 'use_days':
    #             ptype_data.insert(2, {
    #                 "name": "天数",
    #                 "name_en": 'days',
    #                 "type": "number",
    #                 "url": '',
    #                 "value": 1,
    #             })
    #             continue
    #         option_dict = {}
    #         option_obj = form_field_dict.get(str(option.attribute_name), {})
    #         if option.option_type == 'checkbox':
    #             option_default_type = option_obj.get('type')
    #             option_dict['name'] = option_obj.get('name')
    #         else:
    #             option_default_type = None
    #             option_dict['name'] = option.display_name
    #
    #         # 下拉选择框的值单独处理
    #         if option.option_type == 'select' or option_default_type == "select":
    #             if option_default_type:
    #                 # 获取下拉选框默认选项值
    #                 option_default_value = option_obj.get('value')
    #                 option_dict['value'] = option_default_value
    #             else:
    #                 # 获取填写的下拉选框选项值
    #                 option_value = option.attribute_value.split("\n")
    #                 option_list = []
    #                 for ovalue in option_value:
    #                     option_list.append({
    #                         'name': "sel" + str(option_value.index(ovalue)),
    #                         'value': ovalue,
    #                         'selected': True if option_value.index(
    #                             ovalue) == 0 else False
    #                     })
    #                 option_dict['value'] = option_list
    #         else:
    #             # 如果是自定义文本型，value存储text_hint里的内容
    #             # if option.option_type == 'text' and option.text_hint:
    #             #    option_dict['value'] = option.text_hint
    #             # else:
    #             option_dict['value'] = option.attribute_value
    #
    #         if option.attribute_name == 'use_date':
    #             option_dict['url'] = 'http://' + request.headers['HTTP_HOST'] + \
    #                                  '/product/%s/calendar/' % product_id
    #         else:
    #             option_dict['url'] = ''
    #
    #         if option.option_type == 'checkbox':
    #             # 复选框项(name_en使用productorder表字段对应的form field)
    #             option_dict['type'] = option_obj.get('type')
    #             option_dict['name_en'] = option_obj.get('related_name')
    #
    #             # 预填基本信息
    #             if option_dict['name_en'] in last_order_info:
    #                 option_dict['value'] = last_order_info[
    #                     option_dict['name_en']]
    #
    #             if option_dict['name_en'] == 'baby_count':
    #                 is_baby = True
    #                 if product.baby_description:
    #                     # 获取婴携带婴儿说明
    #                     option_dict['placeholder'] = product.baby_description
    #                 else:
    #                     option_dict['placeholder'] = ""
    #             elif option_dict[
    #                 'name_en'] == 'hotel_name' and product.pick_range:
    #                 # 获取酒店说明
    #                 option_dict['placeholder'] = product.pick_range
    #             else:
    #                 option_dict['placeholder'] = option_obj.get('placeholder')
    #
    #             field_list.append(option_dict)
    #             tkey = option_obj.get('category')
    #             tpl_json[tkey].append(option_dict)
    #
    #             option_dict['sort'] = option_obj.get('sort')
    #         else:
    #             # 自定义项
    #             otype = option.option_type
    #             option_dict['type'] = otype
    #             option_dict['name_en'] = 'custom' + "_" + str(option.id)
    #             option_dict['sort'] = 100 + int(option.id)
    #             option_dict['placeholder'] = option.text_hint
    #
    #             custom_option.append(option_dict)
    #             tpl_json[str(option.category)].append(option_dict)
    #
    #     if tpl_json.has_key('basic'):
    #         tpl_json['basic'] = sorted(tpl_json['basic'], \
    #                                    cmp=lambda x, y: cmp(x['sort'],
    #                                                         y['sort']),
    #                                    reverse=False)
    #         ptype_data.extend(tpl_json['basic'])
    #         tpl_json['basic'] = [ptype_data]
    #     else:
    #         tpl_json['basic'] = [ptype_data]
    #
    #     tpl_json['extended'] = sorted(tpl_json['extended'],
    #                                   cmp=lambda x, y: cmp(x['sort'],
    #                                                        y['sort']),
    #                                   reverse=False)
    #     tpl_json['contact'] = sorted(tpl_json['contact'],
    #                                  cmp=lambda x, y: cmp(x['sort'], y['sort']),
    #                                  reverse=False)
    #
    #     return tpl_json, field_list, ptype_data, custom_option, is_baby

    def get_product_types_data(self, request, product_id):
        """
        获取产品类型数据
        """
        count = request.form.getlist('count')
        pcategory = request.form.getlist('pcategory')
        use_days = request.form.getlist('days')
        price = request.form.getlist('price')

        ptype_list = []
        # 添加多组产品类型数据处理
        for i in xrange(len(pcategory)):
            if int(count[i]) == 0:
                continue
            ptype_dict = {}
            ptype_dict['category'] = str(pcategory[i].split('_')[1])
            ptype_dict['id'] = int(pcategory[i].split('_')[0])
            ptype_dict['count'] = count[i]
            if use_days:
                ptype_dict['use_days'] = use_days[i]
            ptype_dict['price'] = price[i]
            ptype_list.append(ptype_dict)

        ptype_ids = [safe_int(x.get('id')) for x in ptype_list]
        ptypes = ProductSKU.objects.filter(
            is_active=True, product__id=product_id, pk__in=ptype_ids)

        # 产品分类(成人，儿童)
        for ptype in ptype_list:
            producttype = ptypes.get(pk=ptype['id'])
            if not producttype:
                ptype_list.remove(ptype)
                continue
            if ptype['category'] == '1':
                ptype.update({'pkey': 'adult'})
            elif ptype['category'] == '2':
                ptype.update({'pkey': 'child'})
            else:
                ptype.update({'pkey': 'null'})

        return ptype_list, ptypes

    def get_user_order_data(self, order_option):
        """
            获取用户填写订单数据(post处理)

        """
        order_option_dict = dict(order_option)
        print 'order_option ----'
        print order_option_dict
        print 'order_option ----'
        exclude_option = [
            'days', 'count', 'ptype', 'pcategory', 'price', 'detail',
            'is_add_product_type', 'csrfmiddlewaretoken'
        ]
        for option in exclude_option:
            if order_option_dict.has_key(option):
                order_option_dict.pop(option)

        checkset_list = []
        custom_option = []
        for k, v in order_option_dict.items():
            custom_option_dict = {}
            if k.find('custom') != -1:
                custom_option_dict["name_en"] = k
                pcat = ProductCustomCategory.objects.get(
                    pk=int(str(k).split("_")[1]))
                custom_option_dict["ename"] = pcat.attribute_name
                custom_option_dict["value"] = order_option.get(k)
                custom_option_dict["name"] = pcat.display_name
                custom_option.append(custom_option_dict)
            else:
                checkset_list.append((k, True))

        return custom_option, checkset_list

    def get_order_or_None(self, product):
        # 判断是否为修改订单
        order_id = safe_int(request.args.get('order_id'))
        order = None
        if not order_id:
            return order
        params = {
            'pk': order_id,
            'status': 1,
            'product': product,
            # 'device_id': request.args.get('device_id'),
        }
        # if request.user.is_authenticated:
        #    params['user'] = request.user
        # else:
        #    params['device_id'] = request.args.get('device_id')
        order = Order.objects.filter(**params).first()
        return order

    def get_last_order_contact_info(self, request):
        device_id = request.args.get('device_id', '').strip()
        if not device_id:
            return {}
        # 获取上一个订单的联系人信息
        orders = ProductOrder.objects.filter(device_id=device_id) \
                     .exclude(contact_email=None).order_by('-pk')[:1]
        if not orders:
            return {}
        order = orders[0]
        return {
            'contact_name': order.contact_name,
            'contact_email': order.contact_email,
            'contact_tel': order.contact_tel,
            'first_name': order.first_name,
            'last_name': order.last_name,
        }

    def get(self, product_id):
        template_var = self._init_data(request)
        # template_var.update(self.get_user_agent_info())
        template_var.update(request.breadtrip)

        device_id = request.args.get('device_id', '').strip()
        order_id = request.args.get('order_id', '')
        plan_id = request.args.get('plan_id', '')

        # product = get_object_or_404(
        #     Product, pk=product_id, is_active=True, published=True)
        print product_id
        product = Product.objects.get(id=product_id, is_active=True,
                                      published=True)
        if not product:
            # abort(404)
            return jsonify({'error_msg': u'该产品不存在'})

        # insure
        # if product.template_id == 6:
        #     url = '/special/product/insure/%s/order/?device_id=%s&order_id=%s&plan_id=%s'
        #     url = url % (product.pk, device_id, order_id, plan_id)
        #     return redirect(url)

        mtu = Mtu.objects.get(target_type=MTU_TYPE.PRODUCT,
                              target_id=product.id)

        if not mtu:
            # abort(404)
            return jsonify({'error_msg': u'该MTU不存在'})

        # mtu = get_object_or_404(
        #     Mtu, target_type=MTU_TYPE.PRODUCT, target_id=product.pk)

        product.mtu_id = mtu.pk
        order = self.get_order_or_None(product)
        plan_id = safe_int(request.args.get('plan_id'))

        is_show_bottom_banner = False
        if order:
            tpl_json = get_order_edit_data(order)
            if order.plan_id and template_var['is_vacation']:
                is_show_bottom_banner = True
        else:
            if plan_id and template_var['is_vacation']:
                is_show_bottom_banner = True
            # 获取产品类型数据
            is_add_product_type, total_price, ptype_data = \
                self.product_type_handle(request, product)

            # 获取产品自定义项数据
            # tpl_json, field_list, ptype_data, custom_option, is_baby = \
            #     self.get_custom_option_data(request, ptype_data, product_id)

            tpl_json = copy.deepcopy(product.product_custom_category)
            print 'tpl_json -------'
            for k, v in tpl_json.items():
                print k, '--', v
            print 'tpl_json ------- end'

            tpl_json['is_add_product_type'] = is_add_product_type
            tpl_json['total_price'] = total_price
            # tpl_json['is_baby'] = is_baby

        template_var.update({
            'request_get': request.args.copy(),
            'device_id': device_id,
            'product': product,
            'tpl_json': json.dumps(tpl_json),
            'is_show_bottom_banner': is_show_bottom_banner,
            'plan_id': plan_id,
            'order_id': safe_int(request.args.get('order_id')),
            'user': request.user  # FIXME zezhou
        })

        print template_var['tpl_json']
        # print template_var['tpl_json']['basic']
        return render_template('mobile/tripproduct/vacation_order.html',
                               # return render_template('1.html',
                               **template_var)

    def save_order_detail(self, post_data, order):
        """
        保存ordel detail数据
        """
        orderdetail = get_object_or_None(OrderDetail, order=order)
        feilds = ['weixin', 'get_on_address', 'delivery_location',
                  'shipping_address', 'take_off_time', 'arrive_time',
                  'ticket_counter', 'hotel_address', 'user_waiting_time']
        params = {}
        for feild in feilds:
            params[feild] = post_data.get(feild)
        if orderdetail:
            orderdetail.__dict__.update(**params)
            orderdetail.save()
        else:
            OrderDetail.objects.create(order=order, **params)
        return

    def post(self, product_id):
        """
            type_id        产品类型id
            category       产品类型标识:adult,child,null
                           非无效的记录可以既包括成人也包括儿童类型
                           无效的记录,放在成人里展示
        """
        template_var = self._init_data(request)
        # template_var.update(self.get_user_agent_info(request))
        template_var.update(request.breadtrip)
        device_id = request.args.get('device_id')
        plan_id = get_objectId(request.args.get('plan_id'))
        # plan = get_object_or_None(UserPlan, pk=plan_id)
        plan = plan_id and UserPlan.objects.get(id=plan_id)

        # 获取用户填写订单数据
        product = Product.objects.get(pk=product_id)
        print 'product_custom_category ----'
        # print product.product_custom_category
        for k, v in product.product_custom_category.items():
            print k, v

        print 'product_custom_category ------'
        custom_option, checkset_list = self.get_user_order_data(request.form)
        order = self.get_order_or_None(request, product)

        # mtu = get_object_or_404(
        #     Mtu, target_type=MTU_TYPE.PRODUCT, target_id=product.pk)

        mtu = Mtu.objects.get(target_type=MTU_TYPE.PRODUCT,
                              target_id=product.id)

        if not mtu:
            # abort(404)
            return jsonify({'error_msg': u'该MTU不存在'})
        product.mtu_id = mtu.pk

        fields = dict(checkset_list)
        print '9' * 99
        print fields
        fields['first_name'] = True
        print '9' * 99

        form = ProductOrderForm(request.form, fields=fields,
                                custom_option=custom_option)
        print form.data

        print '9' * 99
        # 获取产品类型数据
        ptype_list, ptypes = self.get_product_types_data(request, product_id)

        is_show_bottom_banner = False
        if order:
            if order.plan_id and template_var['is_vacation']:
                is_show_bottom_banner = True
        else:
            if plan_id and template_var['is_vacation']:
                is_show_bottom_banner = True

        errmsg = None
        # 查看日期是否可预定
        use_date = request.form.get('date')
        if use_date:
            date = datetime.datetime.strptime(use_date, '%Y-%m-%d').date()
            is_book = get_productsku_blackout_date(ptypes, book_date=date)
            if not is_book:
                errmsg = u"请选择正确的可预定日期"

        if not ptype_list:
            errmsg = u"请填写有效的产品类型信息"

        if form.errors:
            errmsg = form.errors.items()[0][1][0]

        if errmsg:
            # if False:
            template_var.update({
                'request_get': request.args.copy(),
                'device_id': device_id,
                'product': product,
                'is_show_bottom_banner': is_show_bottom_banner,
                'plan_id': plan_id,
                'order_id': safe_int(request.args.get('order_id')),
                'errmsg': errmsg,
                'form': form,
                'user': request.user
            })
            print '8' * 99
            print template_var
            print errmsg
            return render_template(self.template_name, **template_var)


        # form.cleaned_data['device_id'] = device_id or str(uuid.uuid1())
        form.device_id = device_id or str(uuid.uuid1())
        form.product = product

        # 订单详情表数据处理
        exclude_fileds = OrderDetail.get_field_dict()
        order_detail_dict = {}

        # form_dict = copy.deepcopy(form.cleaned_data)
        for field in form:
            if field in exclude_fileds:
                form._fields.pop(field.name)
                order_detail_dict[field.name] = field.data
            if field.name.find("custom") != -1:
                form._fields.pop(field.name)

        # TODO here
        # 保存产品订单
        if order:
            order.__dict__.update(**form.cleaned_data)
            order.date = form.cleaned_data.get('date')
            order.supplier = product.supplier
        else:
            order = ProductOrder(**form.cleaned_data)
            order.supplier = product.supplier
            order.unique_id = str(uuid.uuid1())
            order.plan = plan
        if not order.user and request.user.is_authenticated():
            order.user = request.user

        # 自定义项内容(保存时用填写的英文名称,用于订单详情页及凭证展示)
        if custom_option:
            for option in custom_option:
                option['name_en'] = option['ename']
                option.pop('ename')
            order.custom_option = json.dumps(custom_option)

        order.source = order.get_order_source(request)
        order.save()

        self.save_order_detail(order_detail_dict, order)

        # 保存产品类型订单
        ordertypes = OrderProductType.objects.filter(order=order)
        ordertypes.delete()

        for ptype in ptype_list:
            producttype = ptypes.get(pk=int(ptype['id']))
            ptype_info = producttype.get_info(str(ptype['pkey']))
            if not ptype_info:
                ptype_info = {}

            OrderProductType.objects.create(
                order=order,
                fee=safe_int(ptype_info.get('fee')),
                type=producttype,
                name=producttype.name,
                name_en=producttype.name_en,
                description=ptype_info.get('description'),
                count=ptype['count'],
                category=ptype['category'],
                use_days=ptype.get('use_days')
            )

        # 更新 PlanOrderMtu
        if order.plan:
            order_mtu, created = PlanOrderMtu.objects.get_or_create(
                plan=order.plan, mtu=mtu)
            order_mtu.order = order
            order_mtu.save()

        template_var.update(self.get_user_agent_info(request))

        if template_var['is_breadtrip']:
            url = make_bt_order(request, order)
        elif template_var['is_vacation'] and order.plan:
            template_var['request_get'] = request.args.copy()
            template_var['form'] = form
            template_var['product'] = product
            template_var['go_app'] = True
            template_var['order_id'] = id_encrypt(order.pk)
            return render(request, self.template_name, template_var,
                          use_jinja2=True)
        else:
            url = '/pay/order/%s?device_id=%s' % (
                id_encrypt(order.pk), device_id)
        return redirect(url)


current_app.add_url_rule('/product/<product_id>/order/',
                         view_func=ProductOrderView.as_view(
                             'product_order_view'))
